/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package org.xeerkat.xmpp.server.www;

import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;
import java.sql.SQLException;
import java.util.Iterator;
import java.util.logging.Level;
import org.infoset.xml.Document;
import org.infoset.xml.DocumentLoader;
import org.infoset.xml.Element;
import org.infoset.xml.InfosetFactory;
import org.infoset.xml.ItemConstructor;
import org.infoset.xml.ItemDestination;
import org.infoset.xml.XMLException;
import org.infoset.xml.sax.SAXDocumentLoader;
import org.infoset.xml.util.WriterItemDestination;
import org.restlet.data.CharacterSet;
import org.restlet.data.MediaType;
import org.restlet.data.Status;
import org.restlet.representation.OutputRepresentation;
import org.restlet.representation.Representation;
import org.restlet.representation.StringRepresentation;
import org.restlet.resource.ServerResource;
import org.xeerkat.xmpp.ID;
import org.xeerkat.xmpp.server.XMPPServer;
import org.xeerkat.xmpp.server.db.User;

/**
 *
 * @author alex
 */
public class AllUsersResource extends ServerResource {

   public AllUsersResource()
   {
      setNegotiated(false);
   }
   
   public Representation get() {
      XMPPServer server = (XMPPServer)getContext().getAttributes().get("xmpp.server");
      try {
         final Iterator<User> users = server.getDatabase().getUsers();
         Representation rep = new OutputRepresentation(MediaType.APPLICATION_XML) {
            public void write(OutputStream os)
               throws IOException
            {
               Writer w = new OutputStreamWriter(os,getCharacterSet().toString());
               ItemDestination dest = new WriterItemDestination(w,getCharacterSet().toString());
               ItemConstructor constructor = InfosetFactory.getDefaultInfoset().createItemConstructor();
               try {
                  dest.send(constructor.createDocument());
                  dest.send(constructor.createElement(AdminApplication.USERS));
                  while (users.hasNext()) {
                     User user = users.next();
                     Element userE = constructor.createElement(AdminApplication.USER);
                     userE.setAttributeValue("id", user.getXMPPId().toString());
                     dest.send(userE);
                     try {
                        Iterator<ID> resources = user.getResources();
                        while (resources.hasNext()) {
                           dest.send(constructor.createElement(AdminApplication.RESOURCE));
                           dest.send(constructor.createCharacters(resources.next().toString()));
                           dest.send(constructor.createElementEnd(AdminApplication.RESOURCE));
                        }
                     } catch (SQLException ex) {
                        getLogger().log(Level.SEVERE,"Cannot get resources for user "+user.getXMPPId(),ex);
                     }
                     dest.send(constructor.createElementEnd(AdminApplication.USER));
                  }
                  dest.send(constructor.createElementEnd(AdminApplication.USERS));
                  dest.send(constructor.createDocumentEnd());
               } catch (XMLException ex) {
                  throw new IOException(ex.getMessage());
               }
               w.flush();
            }
            public void release() {
               while (users.hasNext()) {
                  users.next();
               }
            }
         };
         rep.setCharacterSet(CharacterSet.UTF_8);
         setStatus(Status.SUCCESS_OK);
         return rep;
      } catch (SQLException ex) {
         getLogger().log(Level.SEVERE,"Cannot get users from database.",ex);
         setStatus(Status.SERVER_ERROR_INTERNAL);
         return new StringRepresentation("Database error.");
      }
   }
   
   public boolean allowPost() {
      return true;
   }
   
   public Representation post(Representation entity) {
      try {
         Reader r = entity.getReader();
         DocumentLoader loader = new SAXDocumentLoader();
         Document doc = loader.load(r);
         Element top = doc.getDocumentElement();
         if (!top.getName().equals(AdminApplication.USER)) {
            setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
            return new StringRepresentation("Element "+top.getName()+" not allowed.");
         }
         String id = top.getAttributeValue("id");
         XMPPServer server = (XMPPServer)getContext().getAttributes().get("xmpp.server");
         ID xmppid = new ID(id);
         if (server.getDatabase().getUser(xmppid)==null) {
            server.getDatabase().createUser(xmppid);
            setStatus(Status.SUCCESS_NO_CONTENT);
            return null;
         } else {
            setStatus(Status.CLIENT_ERROR_CONFLICT);
            return new StringRepresentation("User "+id+" already exists.");
         }
      } catch (IOException ex) {
         getLogger().log(Level.SEVERE,"I/O error while processing",ex);
         setStatus(Status.SERVER_ERROR_INTERNAL);
         return new StringRepresentation("Database error.");
      } catch (SQLException ex) {
         setStatus(Status.SERVER_ERROR_INTERNAL);
         getLogger().log(Level.SEVERE,"Cannot create user in database.",ex);
         return new StringRepresentation("Database error.");
      } catch (XMLException ex) {
         setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
         return new StringRepresentation(ex.getMessage());
      }
   }
}
